package com.dmcb.common.business.utils;

import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.background.JavaScriptJobManager;
import com.gargoylesoftware.htmlunit.util.Cookie;
import com.gargoylesoftware.htmlunit.util.UrlUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;

/**
 * 网络连接服务
 * Created by long on 2015/12/10.
 */
@Service
public class WebClientUtil {
    static Logger logger = LoggerFactory.getLogger(WebClientUtil.class);

    private static final int PORT = 3128;

    public static final String PROXY_REGION = "yunfu1";

    public static WebClient wc;
    public static WebClient wc2;
    private WebClient wcJs;

    /**
     * 初始化WebClient和Cookie
     *
     * @param cookies COOKIE
     * @return 是否成功
     */
    public WebClient initQichacha(String cookies) {
        WebClient wc = initWc(true, false, false);
        initCookie(wc, cookies, "www.qichacha.com");
        return wc;
    }


    /**
     * 初始化WebClient(翻墙版本)
     *
     * @return WebClient
     */
    public static WebClient initWcForOverTheWall(boolean jsEnabled, boolean cssEnabled, boolean remoteProxy) {
        WebClient wc;
        if (remoteProxy) {
            wc = new WebClient(BrowserVersion.CHROME, "127.0.0.1", 1080);
            logger.info("Proxy host:{}, port:{}", "127.0.0.1", 1080);
        } else {
            wc = new WebClient(BrowserVersion.CHROME);
        }
        return init(jsEnabled, cssEnabled, wc);
    }


    /**
     * 初始化WebClient（根据IP实例化版本）
     *
     * @return WebClient
     */
    public static WebClient initWcByIp(boolean jsEnabled, boolean cssEnabled, String ip, int port) {
        WebClient wc;
        wc = new WebClient(BrowserVersion.CHROME, ip, port);
        logger.info("快代理Proxy host:{}, port:{}", ip, port);
        return init(jsEnabled, cssEnabled, wc);
    }


    /**
     * 初始化WebClient(通用版本)
     *
     * @return WebClient
     */
    public static WebClient initWc(boolean jsEnabled, boolean cssEnabled, boolean remoteProxy) {
        WebClient wc;
        if (remoteProxy) {
            String host = JedisHelper.getIp(PROXY_REGION);
            if (StringUtils.isBlank(host)) {
                wc = new WebClient(BrowserVersion.CHROME);
            } else {
                wc = new WebClient(BrowserVersion.FIREFOX_45, host, PORT);
                logger.info("Proxy host:{}, port:{}", host, PORT);
                final DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) wc.getCredentialsProvider();
                credentialsProvider.addCredentials("kbanquan", "kb102210");
            }
        } else {
            wc = new WebClient(BrowserVersion.CHROME);
        }
        return init(jsEnabled, cssEnabled, wc);
    }


    public static WebClient initForbidDirecter(boolean jsEnabled, boolean cssEnabled, boolean forbidDirecter) {
        WebClient wc = new WebClient(BrowserVersion.CHROME);
        wc.getOptions().setUseInsecureSSL(false);
        wc.getCookieManager().setCookiesEnabled(true);//开启cookie管理
        wc.getOptions().setJavaScriptEnabled(jsEnabled);//开启js解析
        wc.getOptions().setCssEnabled(cssEnabled);//开启css解析
        wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
        wc.getOptions().setThrowExceptionOnScriptError(false);
        wc.getOptions().setTimeout(60000);
        wc.getOptions().setPopupBlockerEnabled(false);
        wc.setJavaScriptTimeout(50000);
        wc.getOptions().setUseInsecureSSL(true);
        wc.getOptions().setRedirectEnabled(forbidDirecter);
        wc.getOptions().setJavaScriptEnabled(false);
        wc.setAjaxController(new NicelyResynchronizingAjaxController()); // will tell your WebClient instance to re-synchronize asynchronous XHR.
        return wc;
    }


    public static WebClient init(boolean jsEnabled, boolean cssEnabled, WebClient wc) {
        wc.getOptions().setUseInsecureSSL(false);
        wc.getCookieManager().setCookiesEnabled(true);//开启cookie管理
        wc.getOptions().setJavaScriptEnabled(jsEnabled);//开启js解析
        wc.getOptions().setCssEnabled(cssEnabled);//开启css解析
        wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
        wc.getOptions().setThrowExceptionOnScriptError(false);
        wc.getOptions().setTimeout(60000);
        wc.getOptions().setPopupBlockerEnabled(false);
        wc.setJavaScriptTimeout(40000);
        wc.getOptions().setUseInsecureSSL(true);
        wc.setAjaxController(new NicelyResynchronizingAjaxController()); // will tell your WebClient instance to re-synchronize asynchronous XHR.
        return wc;
    }

    public void initCookie(WebClient wc, String initCookies, String domain) {
        if (StringUtils.isBlank(initCookies)) {
            return;
        }
        CookieManager cookieManager = wc.getCookieManager();
        // 清除
        cookieManager.clearCookies();
        // 初始化
        String[] cookieArray = initCookies.split(";");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DAY_OF_MONTH, 10);
        Date expire = c.getTime();
        String path = "/";
        for (String str : cookieArray) {
            String[] cookies = str.split("=", 2);
            String name = cookies[0].trim();
            //  String domain = "www.qichacha.com"; // "pspt".equals(name) ? ".qichacha.com" :
            if (cookies.length == 1)
                cookieManager.addCookie(new Cookie(domain, name, "", path, expire, false));
            else
                cookieManager.addCookie(new Cookie(domain, name, cookies[1].trim(), path, expire, false));
        }
    }

    public BufferedImage getPageImage(WebClient wc, String imgUrl) {
        logger.info("WebUtil.buildRequestImage:{}", imgUrl);
        BufferedImage image = WebUtil.buildRequestImage(imgUrl);
        if (image != null) {
            return image;
        }
        logger.info("WebClientUtil getPage:{}", imgUrl);
        if (wc == null) {
            wc = initWc(false, false, false);
        }
        try {
            return ImageIO.read(wc.getPage(imgUrl).getWebResponse().getContentAsStream());
        } catch (Exception e) {
            logger.error("getPageImage error, url={}", imgUrl, e);
            return null;
        }
    }

    public HtmlPage getPage(String url) {
        if (wc == null) {
            wc = initWc(false, false, false);
        }
        logger.info("get page:{}", url);
        try {
            Page page = wc.getPage(url);
            return page instanceof HtmlPage ? (HtmlPage) page : null;
        } catch (SocketException e) {
            // logger.error("getPage error, url={}", url, "SocketException:Connection rest");
            return null;
        } catch (Exception e) {
            //   logger.error("getPage error, url={}", url, e);
            return null;
        }
    }


    public static HtmlPage getPage1(String url) {
        if (wc == null) {
            wc = initWc(false, false, false);
        }
        logger.info("get page:{}", url);
        try {
            Page page = wc.getPage(url);
            return page instanceof HtmlPage ? (HtmlPage) page : null;
        } catch (Exception e) {
            logger.error("getPage error, url={}", url, e);
            return null;
        }
    }

    public static HtmlPage getPageByWebClient(WebClient wc, String url) {
        if (wc == null) {
            wc = initWc(false, false, false);
        }
        logger.info("get page:{}", url);
        try {
            Page page = wc.getPage(url);
            return page instanceof HtmlPage ? (HtmlPage) page : null;
        } catch (Exception e) {
            logger.error("getPage error, url={}", url, e);
            return null;
        }
    }

    /**
     * 初始化WebClient和Cookie
     *
     * @param cookies COOKIE
     * @return 是否成功
     */
    public WebClient initXiGuaZhuShou(String cookies) {
        WebClient wc2 = initWc(false, false, false);
        initCookie(wc2, cookies, "zs.xiguaji.com");
        return wc2;
    }

    public HtmlPage getPageJs(String url) {
        return getPageJs(url, false, false);
    }

    public HtmlPage getPageJs(String url, boolean wait, Boolean proxy) {
        return getPageJs(url, false, proxy);
    }

    public HtmlPage getPageJs(String url, boolean wait) {
        return getPageJs(url, wait, false);
    }

    public HtmlPage getPageJs(String url, boolean wait, boolean proxy) {
        if (wcJs == null) {
            wcJs = initWc(true, true, proxy);
        }
        try {
            Page page = wcJs.getPage(url);
            logger.info("get page url={}, wait={}", url, wait);
            if (wait) {
                JavaScriptJobManager manager = page.getEnclosingWindow().getJobManager();
                int count = manager.waitForJobs(5000);
                System.out.println("count" + count);
                int times = 0;
                while (count > 2) {
                    count = manager.waitForJobs(5000);
                    logger.info("------with in while loop and count:{}---times:{}", count, times);
                    if (times++ >= 10) {
                        break;
                    }
                }
            }
            return page instanceof HtmlPage ? (HtmlPage) page : null;
        } catch (Exception e) {
            logger.error("getPage error, url={}", url, e);
            return null;
        }
    }

    public Document getDoc(String link) {
        HtmlPage element = getPage(link);
        if (element == null) {
            return null;
        }
        return Jsoup.parse(element.asXml());
    }


    /**
     * 获取链接文档
     *
     * @param webClient WebClient
     * @param link      链接
     * @return Document
     */
    public Document getDoc2(WebClient webClient, String link) {
        if (webClient == null) {
            webClient = initWc(false, false, false);
        }
        try {
            Page page = webClient.getPage(link);
            if (page == null || !(page instanceof HtmlPage))
                return null;
            return Jsoup.parse(((HtmlPage) page).asXml());
        } catch (UnknownHostException e) {
            logger.error("UnknownHostException, url={}", link);
            return null;
        } catch (Exception e) {
            logger.error("getPage error, url={}", link, e);
            return null;
        }
    }

    public Document getBaiDuDoc(String link) {
        HtmlPage htmlPage = getPage2(link);
        if (htmlPage == null) {
            return null;
        }
        return Jsoup.parse(htmlPage.asXml());
    }

    public static HtmlPage getPage2(String url) {
        if (wc2 == null) {
            wc2 = new WebClient(BrowserVersion.CHROME);
            wc2.getOptions().setTimeout(15000);
            wc2.getOptions().setMaxInMemory(10 * 1024 * 1024);
            wc2.getOptions().setUseInsecureSSL(true);
            wc2.getOptions().setHistorySizeLimit(2);
            wc2.getOptions().setJavaScriptEnabled(true);//开启js解析
            wc2.setJavaScriptTimeout(10000);
            wc2.getOptions().setCssEnabled(false);
            wc2.setCssErrorHandler(new SilentCssErrorHandler());
            wc2.getCache().setMaxSize(3);
            wc2.getOptions().setThrowExceptionOnFailingStatusCode(false);
            wc2.getOptions().setThrowExceptionOnScriptError(false);
            wc2.getOptions().setPopupBlockerEnabled(false);
            wc2.setAjaxController(new NicelyResynchronizingAjaxController()); // will tell your WebClient instance to re-synchronize asynchronous XHR.
            wc2.setIncorrectnessListener(new IncorrectnessListener() {
                @Override
                public void notify(String s, Object o) {
                }
            });
            wc2.getCookieManager().setCookiesEnabled(false);
        }
        try {
            return wc2.getPage(wc2.getCurrentWindow().getTopWindow(), new WebRequest(UrlUtils.toUrlUnsafe(url), wc2.getBrowserVersion().getHtmlAcceptHeader()), false);
        } catch (Exception e) {
            logger.error("getPage2 error, url={}, msg={}", url, e.getMessage());
            return getPage1(url);
        }
    }

//    public static void main(String args[]) {
//        WebClientUtil webClientUtil = new WebClientUtil();
//        // String data = WebUtil.sendGet("https://mp.weixin.qq.com/s/dCiocbjbrthzzv-l19S1jA");
//        WebClientUtil.wc = WebClientUtil.initWc(true, false, false);
//        Document doc = webClientUtil.getDoc2(wc, "http://sh.qihoo.com/mob/transcoding?url=9ded9dcf8284b66e4");
//        System.out.println(doc.toString());
//    }


}
